package cn.android666.recorddemowithnoise

import android.annotation.SuppressLint
import android.media.*
import android.os.Environment
import android.os.Process
import android.text.format.DateFormat
import java.io.File
import java.io.FileOutputStream
import java.nio.ByteBuffer
import kotlin.concurrent.thread

class AudioRecorder {

    private var record = false

    @SuppressLint("MissingPermission")
    fun startRecord() {
        if (record) return
//        val sampleRateInHz = 44100
        val sampleRateInHz = 8000
        // 注：音频源不要使用MIC，应该使用VOICE_COMMUNICATION，如果可用的话，它会自动进行回声消除
//        val audioSource = MediaRecorder.AudioSource.MIC // 在北京执法仪上，使用MIC会导致录的白噪音很大声，使用VOICE_COMMUNICATION可以避免这个问题
        val audioSource = MediaRecorder.AudioSource.VOICE_COMMUNICATION
        val channelConfig = AudioFormat.CHANNEL_IN_MONO
        val audioFormat = AudioFormat.ENCODING_PCM_16BIT
        val minBufferSize = AudioRecord.getMinBufferSize(sampleRateInHz, channelConfig, audioFormat)
        val audioRecord = AudioRecord(audioSource, sampleRateInHz, channelConfig, audioFormat, minBufferSize)
        if (audioRecord.state != AudioRecord.STATE_INITIALIZED) {
            printLog("录音失败：初始化AudioRecord失败")
            return
        }
        thread {
//            recordAsPcm(audioRecord, minBufferSize)
            val bitDepth = if (audioFormat == AudioFormat.ENCODING_PCM_16BIT) 16 else TODO("位深处理")
            val channelCount = if (channelConfig == AudioFormat.CHANNEL_IN_MONO) 1 else 2
            recordAsWav(audioRecord, minBufferSize, sampleRateInHz, bitDepth, channelCount)
        }
    }

    fun stopRecord() {
        record = false
    }

    /** 录制为WAV */
    private fun recordAsWav(audioRecord: AudioRecord, minBufferSize: Int, sampleRateInHz: Int, bitDepth: Int, channelCount: Int) {
        printLog("开始录音")
        Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_AUDIO)
        audioRecord.startRecording()
        val byteBuffer = ByteArray(minBufferSize)
        val fileDir = Environment.getExternalStorageDirectory()
        val fileName = "${DateFormat.format("yyyy_MM_dd_HHmmss", System.currentTimeMillis())}.wav"
        val file = File(fileDir, fileName)
        val wavWriter = WavWriter(file, sampleRateInHz, bitDepth, channelCount)
        record = true
        var len = 0
        while (record && audioRecord.read(byteBuffer, 0, minBufferSize).also { len = it } > 0) {
            wavWriter.writeData(byteBuffer, 0, len)
        }
        record = false
        audioRecord.stop()
        audioRecord.release()
        wavWriter.close()
        printLog("录音结束，文件：${file.absoluteFile}")
    }

    /** 录制为PCM */
    private fun recordAsPcm(audioRecord: AudioRecord, minBufferSize: Int) {
        printLog("开始录音")
        Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_AUDIO)
        audioRecord.startRecording()
        val byteBuffer = ByteBuffer.allocateDirect(minBufferSize)
        val fileDir = Environment.getExternalStorageDirectory()
        val fileName = "${DateFormat.format("yyyy_MM_dd_HHmmss", System.currentTimeMillis())}.pcm"
        val file = File(fileDir, fileName)
        val fos = FileOutputStream(file)
        val channel = fos.channel
        record = true
        while (record && audioRecord.read(byteBuffer, minBufferSize) > 0) {
            channel.write(byteBuffer)
            byteBuffer.clear()
        }
        record = false
        audioRecord.stop()
        audioRecord.release()
        channel.close()
        fos.close()
        printLog("录音结束，文件：${file.absoluteFile}")
    }

}